#!/usr/bin/env python
#coding=utf-8

import time
from hashlib import md5
from xpinyin import Pinyin
from flask import request, session, current_app, flash, make_response

from codingabc.database import db
from app.services.qiniu_upload import QiNiuOSS
from app.services.xsl import XLSWriter, XlsDoc
from codingabc.helpers import toint, log_debug, log_info, log_error, log_debug, randomstr, ismobile, format_timestamp, get_count
from app.helpers.sms import yunpian_single
from app.helpers.date_time import current_timestamp
from app.models.user import User, UserCheckCode

class UserSaveService(object):
    """保存用户信息service"""
    def __init__(self, uid=0):
        self.errmsg       = {}
        self.user         = None
        self.cs_id        = 0
        self.py           = Pinyin()

    def _check_param(self, form):
        """检查必须参数"""
        required_param_list = ['nickname', 'gender']
        for param in required_param_list:
            val = form.get(param, '')
            val = val.strip()
            if not val:
                self.errmsg[param] = u'必填项'

        mobile        = form.get('mobile', '').strip()
        parent_mobile = form.get('parent_mobile', '').strip()
        mother_mobile = form.get('mother_mobile', '').strip()
        uid           = toint(form.get('uid','0'))
        gender        = toint(form.get('gender', 0))

        if mobile and not ismobile(mobile):
            self.errmsg['mobile'] = u'会员手机号码不正确'

        if parent_mobile and not ismobile(parent_mobile):
            self.errmsg['parent_mobile'] = u'父亲手机号码不正确'

        if mother_mobile and not ismobile(mother_mobile):
            self.errmsg['mother_mobile'] = u'母亲手机号码不正确'

        has_mobile = User.query.filter(User.mobile == mobile).first()

        if uid <= 0 and has_mobile and mobile:
            self.errmsg['mobile'] = u'新增会员手机号码已经存在'

        if gender not in (1,2):
            self.errmsg['gender'] = u'请选择正确的性别'

    def save(self, form):
        """保存修改信息"""
        self._check_param(form)

        if self.errmsg:
            return self.errmsg

        uid              = toint(form.get('uid','0'))                  # 一、基本信息
        check_type       = toint(form.get('check_type','0'))
        nickname         = form.get('nickname', '').strip()
        pinyin           = form.get('pinyin', '').strip()
        mobile           = form.get('mobile', '').strip()
        gender           = toint(form.get('gender', '0'))
        birthday         = form.get('birthday', '').strip()

        id_no            = form.get('id_no', '').strip()               # 二、证件信息
        id_front_img     = request.files.get('id_front_img', None)
        id_back_img      = request.files.get('id_back_img', None)
        parent_mobile    = form.get('parent_mobile', '').strip()
        mother_mobile    = form.get('mother_mobile', '').strip()
        school_name      = form.get('school_name', '').strip()
        grade            = form.get('grade', '').strip()
        email            = form.get('email', '').strip()
        passport_no      = form.get('passport_no', '').strip()
        pas_valid_time   = form.get('pas_valid_time', '').strip()
        pas_sign_address = form.get('pas_sign_address', '').strip()
        pas_sign_type    = toint(form.get('pas_sign_type','3'))
        pas_front_img    = request.files.get('pas_front_img', None)
        pas_back_img     = request.files.get('pas_back_img', None)
        ga_no            = form.get('ga_no', '').strip()
        ga_valid_time    = form.get('ga_valid_time', '').strip()
        ga_sign_address  = form.get('ga_sign_address', '').strip()
        ga_sign_type     = toint(form.get('ga_sign_type','0'))
        ga_front_img     = request.files.get('ga_front_img', None)
        ga_back_img      = request.files.get('ga_back_img', None)

        sat_accounts     = form.get('sat_accounts', '').strip()       # 三、考试帐号信息
        sat_password     = form.get('sat_password', '').strip()
        act_accounts     = form.get('act_accounts', '').strip()
        act_password     = form.get('act_password', '').strip()
        role_name        = session.get('role_name')

        self.cs_id       = toint(form.get('level3_name', '0'))              # 四、来源渠道

        birthday = time.mktime(time.strptime(birthday,'%Y-%m-%d')) if birthday and birthday > 0 else 0

        if pas_valid_time and pas_valid_time > 0:
            pas_valid_time = time.mktime(time.strptime(pas_valid_time,'%Y-%m-%d'))
        else:
            pas_valid_time = 0

        if ga_valid_time and ga_valid_time > 0:
            ga_valid_time = time.mktime(time.strptime(ga_valid_time,'%Y-%m-%d'))
        else:
            ga_valid_time = 0

        if uid <= 0:
            user_uid = session.get('uid')
            founder = User.query.get_or_404(user_uid)
            self.user = User.create(add_time=int(time.time()), founder=founder.nickname)
            self.cs_id = founder.cs_id if role_name == u'老师' else self.cs_id
        else:
            self.user = User.query.get_or_404(uid)
            self.cs_id = self.user.cs_id if role_name == u'老师' else self.cs_id

        if self.errmsg:
            return self.errmsg

        oss = QiNiuOSS('certificate', 'image', current_app.config['SAVE_TARGET_PATH'])
        if id_front_img:
            try:
                oss.save(id_front_img)
                id_front_img = oss.put_to_oss()
            except IOError as e:
                self.errmsg['id_front_img'] = u'只允许是图片文件'
            except Exception as e:
                self.errmsg['id_front_img'] = u'上传失败'

        if id_back_img:
            try:
                oss.save(id_back_img)
                id_back_img = oss.put_to_oss()
            except IOError as e:
                self.errmsg['id_back_img'] = u'只允许是图片文件'
            except Exception as e:
                self.errmsg['id_back_img'] = u'上传失败'

        if pas_front_img:
            try:
                oss.save(pas_front_img)
                pas_front_img = oss.put_to_oss()
            except IOError as e:
                self.errmsg['pas_front_img'] = u'只允许是图片文件'
            except Exception as e:
                self.errmsg['pas_front_img'] = u'上传失败'

        if pas_back_img:
            try:
                oss.save(pas_back_img)
                pas_back_img = oss.put_to_oss()
            except IOError as e:
                self.errmsg['pas_back_img'] = u'只允许是图片文件'
            except Exception as e:
                self.errmsg['pas_back_img'] = u'上传失败'

        if ga_front_img:
            try:
                oss.save(ga_front_img)
                ga_front_img = oss.put_to_oss()
            except IOError as e:
                self.errmsg['ga_front_img'] = u'只允许是图片文件'
            except Exception as e:
                self.errmsg['ga_front_img'] = u'上传失败'

        if ga_back_img:
            try:
                oss.save(ga_back_img)
                ga_back_img = oss.put_to_oss()
            except IOError as e:
                self.errmsg['ga_back_img'] = u'只允许是图片文件'
            except Exception as e:
                self.errmsg['ga_back_img'] = u'上传失败'

        id_front_img  = id_front_img if id_front_img else self.user.id_front_img
        id_back_img   = id_back_img if id_back_img else self.user.id_back_img
        pas_front_img = pas_front_img if pas_front_img else self.user.pas_front_img
        pas_back_img  = pas_back_img if pas_back_img else self.user.pas_back_img
        ga_front_img  = ga_front_img if ga_front_img else self.user.ga_front_img
        ga_back_img   = ga_back_img if ga_back_img else self.user.ga_back_img

        # 如果是个人资料修改则更新session
        if check_type == 2:
            session['nickname'] = nickname
            session['gender']   = gender
            session['mobile']   = mobile

            # 修改用户昵称，创建人也要一起修改
            User.query.filter(User.founder == self.user.nickname).update({'founder':nickname})

        self.user.update(nickname=nickname,
                         pinyin=pinyin,
                         mobile=mobile,
                         gender=gender,
                         birthday=birthday,
                         id_no=id_no,
                         id_front_img=id_front_img,
                         id_back_img=id_back_img,
                         parent_mobile=parent_mobile,
                         mother_mobile=mother_mobile,
                         school_name=school_name,
                         grade=grade,
                         email=email,
                         passport_no=passport_no,
                         pas_valid_time=pas_valid_time,
                         pas_sign_address=pas_sign_address,
                         pas_sign_type=pas_sign_type,
                         pas_front_img=pas_front_img,
                         pas_back_img=pas_back_img,
                         ga_no=ga_no,
                         ga_valid_time=ga_valid_time,
                         ga_sign_address=ga_sign_address,
                         ga_sign_type=ga_sign_type,
                         ga_front_img=ga_front_img,
                         ga_back_img=ga_back_img,
                         sat_accounts=sat_accounts,
                         sat_password=sat_password,
                         act_accounts=act_accounts,
                         act_password=act_password,
                         cs_id=self.cs_id,
                         update_time=int(time.time()),
                         commit=True)
        return {}


class PasswordSaveService(object):
    """修改密码service"""
    def __init__(self, uid=0):
        self.errmsg       = {}
        self.user         = None

    def _check_param(self, form):
        """检查密码"""
        required_param_list = ['password', 'password1']
        for param in required_param_list:
            val = form.get(param, '').strip()
            if not val:
                self.errmsg[param] = u'必填项'

        form = request.form
        password  = form.get('password', '')
        password1 = form.get('password1', '')

        if password != password1:
            self.errmsg['password1'] = u'两次输入的密码不一致'

    def save(self, form):
        """保存密码"""
        self._check_param(form)

        if self.errmsg:
            return self.errmsg

        uid = session.get('uid')

        form     = request.form
        password = form.get('password','')

        # 获取随机密码
        salt = randomstr(6)
        md5_password = md5(password).hexdigest()

        self.user = User.query.filter(User.uid == uid).first()

        if self.user.password == password:
            flash('...............')

        self.user.salt = salt
        self.user.password = md5(md5_password + salt).hexdigest()
        db.session.commit()

        log_info('self.user.salt:%s, self.user.password:%s' % (self.user.salt, self.user.password))


        return {}

class UserService(object):
    """用户services"""
    def __init__(self):
        super(UserService, self).__init__()


    def user_list(self):
        """用户列表"""
        u_list = User.query.all()

        return u_list


    def get_user_nickname(self):
        """获取用户昵称"""

        user_list = self.user_list()
        USER_NICKNAME = {}
        for user in user_list:
            USER_NICKNAME[user.uid] = user.nickname

        return USER_NICKNAME


    def get_user_mobile(self):
        """获取用户手机号码"""

        user_list = self.user_list()

        USER_MOBILE = {}
        for user in user_list:
            USER_MOBILE[user.uid] = user.mobile

        return USER_MOBILE


    def get_user_gender(self):
        """获取用户性别"""
        user_list = self.user_list()

        USER_GENDER = {}
        GENDER = {0:u'默认', 1:u'男', 2:u'女'}

        for user in user_list:
            USER_GENDER[user.uid] = GENDER.get(user.gender, '')

        return USER_GENDER


    def get_user_nickname_pinyin(self):
        """获取用户昵称拼音"""
        user_list = self.user_list()

        USER_NICKNAME_PINYIN = {}
        for user in user_list:
            USER_NICKNAME_PINYIN[user.uid] = user.pinyin

        return USER_NICKNAME_PINYIN


    def get_user_mother_mobile(self):
        """获取用户母亲手机号码"""
        user_list = self.user_list()

        MOTHER_MOBILE = {}

        for user in user_list:
            MOTHER_MOBILE[user.uid] = user.mother_mobile

        return MOTHER_MOBILE

    def get_user_birthday(self):
        """获取用户出生年月"""
        user_list = self.user_list()

        USER_BIRTHDAY = {}
        for user in user_list:
            USER_BIRTHDAY[user.uid] = user.birthday

        return USER_BIRTHDAY


class AccountSmsService(object):
    """ 帐户短信Service """

    def __init__(self, mobile, check_type):
        self.msg                 = ''
        self.user                = None
        self.mobile              = mobile
        self.check_type          = check_type
        self.check_type_list     = [1, 2, 3]    # 验证类型: 0.默认; 1.注册登录; 2.绑定/更换; 3.密码重置;
        self.current_time        = current_timestamp()
        self.SMS_APP_NAME        = current_app.config['SMS_APP_NAME']
        self.SMS_DAY_LIMIT       = current_app.config['SMS_DAY_LIMIT']
        self.SMS_INTERVAL_MINUTE = current_app.config['SMS_INTERVAL_MINUTE']
        self.SMS_CODE_LENGTH     = current_app.config['SMS_CODE_LENGTH']
        self.SMS_TEMPLATE_DICT   = current_app.config['SMS_TEMPLATE_DICT']

        if self.check_mobile():
            self.user = User.query.filter(User.mobile == self.mobile).first()

    def check_mobile(self):
        """ 检查手机号码 """

        if not self.mobile:
            self.msg = u'手机号码为空'
            return False

        if not ismobile(self.mobile):
            self.msg = u'手机号码不正确'
            return False

        return True

    def check_code_type(self, is_create=True):
        """ 检查验证码类型 """

        if self.check_type not in self.check_type_list:
            self.msg = u'验证码类型错误'

        if is_create:
            if self.check_type == 1 and self.user:
                self.msg = u'%s已经被注册，请更换一个手机号码' % self.mobile

            if self.check_type in (2, 3) and not self.user:
                self.msg = u'帐号不存在'

        if self.msg:
            return False

        return True

    def check_code(self, code):
        """ 校验验证码 """

        if not code:
            self.msg = u'验证码为空'
            return False

        ucc = UserCheckCode.query.filter(UserCheckCode.mobile == self.mobile).\
                    filter(UserCheckCode.check_type == self.check_type).\
                    filter(UserCheckCode.check_code == code).\
                    order_by(UserCheckCode.ucc_id.desc()).first()
        if not ucc:
            self.msg = u'验证码无效'
            return False

        if ucc.expire_time < self.current_time:
            log_info('[InfoServicesUserCheckCode] is expired: mobile:%s current_time:%d, expire_time:%d'
                    % (self.mobile, self.current_time, ucc.expire_time))
            self.msg = u'验证码已过期，请重新获取。'
            return False

        return True

    def is_repeat(self):
        """ 验证码在有效时间内不重复发送 """

        ucc = UserCheckCode.query.filter(UserCheckCode.mobile == self.mobile).\
                    filter(UserCheckCode.check_type == self.check_type).\
                    filter(UserCheckCode.expire_time >= self.current_time).first()
        if ucc:
            self.msg = u'请%d分钟后再获取' % self.SMS_INTERVAL_MINUTE
            return True

        return False

    def sms_day_limit_surplus(self):
        """ 24小时内获取验证码的剩余次数 """

        min_time = self.current_time - 24*60*60

        day_limit_query = UserCheckCode.query.filter(UserCheckCode.mobile == self.mobile).\
                                filter(UserCheckCode.check_type == self.check_type).\
                                filter(UserCheckCode.expire_time >= min_time).\
                                filter(UserCheckCode.expire_time < self.current_time)
        day_sms_count   = get_count(day_limit_query)

        surplus = self.SMS_DAY_LIMIT - day_sms_count
        surplus = surplus if surplus > 0 else 0

        return surplus

    def create_code(self):
        """ 创建验证码 """

        return randomstr(self.SMS_CODE_LENGTH, 1)

    def create_content(self, code):
        """ 创建短信内容 """

        return u'【' + self.SMS_APP_NAME + u'】' + self.SMS_TEMPLATE_DICT.get('general_code').format(code=code)

    def send(self, code, content):
        """
        发送短信
        @return: int 0:错误; >0:短信有效时间
        """

        interval_minute = current_app.config['SMS_INTERVAL_MINUTE']

        # 发送短信
        if not yunpian_single(self.mobile, content):
            return 0

        expire_time = self.current_time + interval_minute*60
        UserCheckCode.create(mobile=self.mobile, check_code=code,
                             expire_time=expire_time, check_type=self.check_type,
                             commit=True)

        return interval_minute
